/*
 * Serial.c
 *
 *  Created on: 09.02.2010
 *      Author: Lunar
 */
#include <avr32/io.h>
#include <stdarg.h>
#include "compiler.h"
#include "intc.h"
#include "stdio.h"

// TXD : USART3 : PB11
// RXD : USART3 : PB10

#define InternalBufferMask 1023
 U8 serialInternalBuffer[1024];
volatile static U16 serialBufferIn = 0, serialBufferOut = 0;

void SerialCharAppen(char c){
	while (((serialBufferIn + 1) & InternalBufferMask) == serialBufferOut);
	serialInternalBuffer[serialBufferIn] = c;
	serialBufferIn = (serialBufferIn + 1) & InternalBufferMask;
	AVR32_USART3.ier = AVR32_USART_IER_TXEMPTY_MASK;	
}


void SerialOut(char *s) {
	while (*s) {
		if (*s == '\n'){
			SerialCharAppen('\r');
		}
		SerialCharAppen(*s);
		s++;
	}

}


__attribute__((__interrupt__)) void SerialInterupt(void){
	AVR32_USART3.thr = serialInternalBuffer[serialBufferOut];
	serialBufferOut = (serialBufferOut +1) & InternalBufferMask;
	if (serialBufferIn == serialBufferOut){
		AVR32_USART3.idr = AVR32_USART_IER_TXEMPTY_MASK;
	}
}

void SerialInit(void) {
	// Controlle der beiden Pins an den UART
	AVR32_GPIO.port[1].pmr0s = 1 << 11 | 1 << 10;
	AVR32_GPIO.port[1].pmr1c = 1 << 11 | 1 << 10;
	AVR32_GPIO.port[1].gperc = 1 << 11 | 1 << 10;

	AVR32_USART3.cr = AVR32_USART_CR_TXEN_MASK | AVR32_USART_CR_RXEN_MASK;
	AVR32_USART3.mr = 1 << AVR32_USART_MR_NBSTOP_OFFSET
			| AVR32_USART_MR_PAR_NONE << AVR32_USART_MR_PAR_OFFSET
			| AVR32_USART_MR_CHRL_8 << AVR32_USART_MR_CHRL_OFFSET;
	AVR32_USART3.brgr = 36;
	AVR32_USART3.cr = AVR32_USART_CR_RSTRX_MASK;
	INTC_register_interrupt(SerialInterupt, AVR32_USART3_IRQ,3);
}


void SerialDump(void* adr, U16 size){
	char buffer[64];
	U8* content = adr;
	snprintf(buffer, 64, "Zeige Adresse: 0x%04X %04X mit %u Bytes:\r\n  (0000)%04X]  ", (U16)((U32)adr>>16), (U16)(U32)adr, size, (U16)(U32)adr);
	SerialOut(buffer);
	U16 count = 0;
	while (size>count){
		if ((count%16 == 15)&&!(size>count+1)) snprintf(buffer, 64," %02X ", *content );
		else if (count%16 == 15) snprintf(buffer, 64," %02X \r\n  (%04X)%04X]  ", *content,count+1, (U16)(U32)content+1 );
		else if (count%8 == 7) snprintf(buffer, 64," %02X :", *content);
		else snprintf(buffer, 64," %02X", *content);
		content ++;
		SerialOut(buffer);
		count++;
	}
	SerialOut("\n\r");

}


void _printf( const char* fmt, ... )
{
	char buffer[80];

	va_list args;
	va_start( args, fmt );
	vsnprintf( buffer, sizeof  buffer,  fmt, args );
	va_end( args );

	SerialOut( buffer );
}
